﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Linq;
using SMSPanasonic.Business;

namespace SMSPanasonic
{
    public partial class PanasonicService : ServiceBase
    {
        Thread workerMTReportThread;
        Thread processMoThread;
        Thread[] workerThreads;
        SMSTask[] arrSMSTask;

        SMSGetMTReport smsGetMTReport;
        SMSMOSend smsMoSend;
        SMSMTAutoSend smsMtAutoSend;

        int numOfTotalMTThread = 0;
        private static List<SmsRouter> SMSPanasonicMTRouterList = SmsRouter.GetAll().FindAll(obj => !obj.RouterType.IsNull && obj.RouterType.Value == "MTROUTER");
        private static SmsRouter getMtReportRouter = SmsRouter.GetAll().Find(obj => !obj.RouterType.IsNull && obj.RouterType.Value == "MTREPORT");

        public void StartFromDebugger(string[] args)
        {
            OnStart(args);
        }

        public static List<SmsRouter> MTRouterList
        {
            get
            {
                return SMSPanasonicMTRouterList;
            }
        }

        public PanasonicService()
        {
            InitializeComponent();
            try
            {
                try
                {
                    if (!System.Diagnostics.EventLog.SourceExists("PanasonicLogSource"))
                        System.Diagnostics.EventLog.CreateEventSource("PanasonicLogSource", "PanasonicLog");

                    eventLog.Source = "PanasonicLogSource";
                    // the event log source by which 

                    //the application is registered on the computer

                    eventLog.Log = "PanasonicLog";

                }
                catch (Exception ex)
                {
                    eventLog.WriteEntry("Message:" + ex.Message + " Source:" + ex.Source + " Stack Trace:" + ex.StackTrace, EventLogEntryType.Error);
                    //Common.WriteLog(ex, "SMSPanasonicTask");
                }
            }
            catch (Exception ext)
            {
                eventLog.WriteEntry(ext.Message, EventLogEntryType.Error);
            }
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                //Dăng ký sqlNotification
                new SQLNotifier("pa_MessagePattern").Start();
                new SQLNotifier("OperatorPrefixCode").Start();
                //Truoc khi Start phai cap nhat tat ca cac trang thai PROCCESSING tro ve trang thai binh thuong
                //UPDATE [dbo].[SmsOutWaiting] SET [Status] = 'PENDING', [RetryOnFailReqTimes] = NULL, [RetryOnTimeOutReqTimes] = NULL, [ThreadExecute] = NULL, [LastTimeProcess] = NULL
                numOfTotalMTThread = SMSPanasonicMTRouterList.Sum(item => item.NumOfThread.Value);

                arrSMSTask = new SMSTask[numOfTotalMTThread];
                workerThreads = new Thread[numOfTotalMTThread];
                int i = 0;
                foreach (SmsRouter item in SMSPanasonicMTRouterList)
                {
                    for (int j = 0; j < item.NumOfThread.Value; j++)
                    {
                        arrSMSTask[i] = new SMSTask(i + 1, item, eventLog);
                        // set properties on the object
                        arrSMSTask[i].ServiceStarted = true;
                        arrSMSTask[i].StatusPending = SmSStatus.Pending;
                        arrSMSTask[i].StatusPendingProccessing = SmSStatus.PendingProcessing;
                        arrSMSTask[i].StatusTimeOut = SmSStatus.RetryOnTimeOut;
                        arrSMSTask[i].StatusTimeOutProccessing = SmSStatus.RetryOnTimeOutProcessing;
                        arrSMSTask[i].StatusFail = SmSStatus.RetryOnFail;
                        arrSMSTask[i].StatusFailProccessing = SmSStatus.RetryOnFailProcessing;

                        arrSMSTask[i].Interval = Properties.Settings.Default.Interval;
                        arrSMSTask[i].RetryOnFailReqDuration = Properties.Settings.Default.RetryOnFailReqDuration; //5phut
                        arrSMSTask[i].RetryOnFailReqTimes = Properties.Settings.Default.RetryOnFailReqTimes;
                        arrSMSTask[i].RetryOnTimeOutReqDuration = Properties.Settings.Default.RetryOnTimeOutReqDuration;
                        arrSMSTask[i].RetryOnTimeOutReqTimes = Properties.Settings.Default.RetryOnTimeOutReqTimes;

                        // create a thread and attach to the object
                        ThreadStart st = new ThreadStart(arrSMSTask[i].ExecuteTask);
                        workerThreads[i] = new Thread(st);

                        workerThreads[i].Start();
                        i += 1;
                    }
                }
                //Khoi tao thread lay report
                smsGetMTReport = new SMSGetMTReport(1, getMtReportRouter, eventLog);
                smsGetMTReport.ServiceStarted = true;
                ThreadStart stMTReport = new ThreadStart(smsGetMTReport.ExecuteTask);
                workerMTReportThread = new Thread(stMTReport);
                workerMTReportThread.Start();

                //Khởi tạo thread lấy MO và xử lý
                smsMoSend = new SMSMOSend(eventLog);
                smsMoSend.ServiceStarted = true;
                processMoThread = new Thread(smsMoSend.ExecuteTask);
                processMoThread.Start();

                //Khởi tạo thread tự động lấy gửi MT khi không yêu cầu Happy call
                smsMtAutoSend = new SMSMTAutoSend(eventLog);
                smsMtAutoSend.ServiceStarted = true;
                (new Thread(smsMtAutoSend.ExecuteTask)).Start();
            }
            catch (Exception ext)
            {
                eventLog.WriteEntry(ext.Message, EventLogEntryType.Error);
            }
        }

        protected override void OnStop()
        {
            try
            {
                for (int i = 0; i < numOfTotalMTThread; i++)
                {
                    // set flag to stop worker thread
                    arrSMSTask[i].ServiceStarted = false;
                    smsGetMTReport.ServiceStarted = false;
                    smsMoSend.ServiceStarted = false;
                    smsMtAutoSend.ServiceStarted = false;

                    // give it a little time to finish any pending work
                    workerThreads[i].Join(new TimeSpan(0, 0, 30));
                }
            }
            catch (Exception ext)
            {
                eventLog.WriteEntry(ext.Message, EventLogEntryType.Error);
            }
        }
    }
}
